/*
 * @Author: Clark
 * @Email: haixuanwoTxh@gmail.com
 * @Date: 2023-01-04 16:46:05
 * @LastEditors: Clark
 * @LastEditTime: 2023-01-04 17:09:04
 * @Description: file content
 */

#include "apue.h"

void pr_stdio(const char*, FILE*);
int is_unbuffered(FILE*);
int is_linebuffered(FILE*);
int buffer_size(FILE*);

int main()
{
    FILE* fp = NULL;

    fputs("enter any character\n", stdout);
    if (EOF == getchar())
    {
        err_sys("getchar error");
    }
    fputs("one line to standard error\n", stderr);

    pr_stdio("stdin", stdin);
    pr_stdio("stdout", stdout);
    pr_stdio("stderr", stderr);

    fp = fopen("/etc/passwd", "r");
    if (NULL == fp)
    {
        err_sys("fopen error");
    }

    if (EOF == getc(fp))
    {
        err_sys("getc error");
    }

    pr_stdio("/etc/passwd", fp);
    exit(0);
}

void pr_stdio(const char *name, FILE *fp)
{
	printf("stream = %s, ", name);
	if (is_unbuffered(fp))
    {
		printf("unbuffered");
    }
    else if (is_linebuffered(fp))
	{
        printf("line buffered");
    }
	else /* if neither of above */
	{
        printf("fully buffered");
    }
	printf(", buffer size = %d\n", buffer_size(fp));
}

/*
 * The following is nonportable.
 */

#if defined(_IO_UNBUFFERED)

int
is_unbuffered(FILE *fp)
{
	return(fp->_flags & _IO_UNBUFFERED);
}

int
is_linebuffered(FILE *fp)
{
	return(fp->_flags & _IO_LINE_BUF);
}

int
buffer_size(FILE *fp)
{
	return(fp->_IO_buf_end - fp->_IO_buf_base);
}

#elif defined(__SNBF)

int
is_unbuffered(FILE *fp)
{
	return(fp->_flags & __SNBF);
}

int
is_linebuffered(FILE *fp)
{
	return(fp->_flags & __SLBF);
}

int
buffer_size(FILE *fp)
{
	return(fp->_bf._size);
}

#elif defined(_IONBF)

// #ifdef _LP64
// #define _flags __pad[4]
// #define _ptr __pad[1]
// #define _base __pad[2]
// #endif

int is_unbuffered(FILE *fp)
{
	return(fp->_flags & _IONBF);
}

int is_linebuffered(FILE *fp)
{
	return(fp->_flags & _IOLBF);
}

int buffer_size(FILE *fp)
{
#ifdef _LP64
	//return(fp->_base - fp->_ptr);
    return (fp->_IO_buf_end - fp->_IO_buf_base);
#else
	return(BUFSIZ);	/* just a guess */
#endif
}

#else

#error unknown stdio implementation!

#endif
